#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Filename: grupo_de_resolucion.py

##
# Módulos del sistema
from datetime import datetime
from sqlobject.sqlbuilder import LIKE, AND

##
# Módulos propios
try:
    from database import Ticket, Intervencion, HistorialDeClasificacion
    from database import HistorialDeEstado, Estado, Observacion, Clasificacion
    from database import GrupoDeResolucion
except ImportError, error:
    print error
    print "Importando clases de BD. 'grupo_de_resolucion.py'"
"""
class GrupoDeResolucion:
    def __init__(self, grupo):
        self.grupo = grupo

    def crearClasificacion(self, nombre, descripcion, grupos_asociados):
        pass

    def buscarClasificaciones(self, tipo):
        pass

    def modificarClasificacion(self, nombre, estado, descripcion,
            grupos_asociados, clasificacion):
        pass

    def actualizar_estado_intervencion(self, intervencion, estado, fecha):
        intervencion.actualizar_estado_intervencion(estado, fecha)
        #intervencion.set(estado=estado, fecha=datetime.now())
    
    def agregar_observacion(self, intervencion, descripcion, usuario, fecha,
            grupo):
        intervencion.agregar_observaciones(descripcion,
                usuario,
                fecha,
                grupo)
    def cambiar_estado_ticket(self, estado, usuario, intervencion):
        dic = {'Resuelta': 'Solucionado a la espera OK',
                'En espera por grupo': 'No Solucionado',
                'Trabajando': 'Abierto derivado',
                'Finalizada': 'No Solucionado'}

        nombre = dic.get(estado)
        if nombre:
            if nombre =='Solucionado a la espera OK':
                if self.intervenciones_pendientes(intervencion):
                    nombre = 'No Solucionado'
            consulta = list(Estado.selectBy(nombre=nombre))
            if consulta:
                nuevo_estado_ticket = consulta[0]
                fecha = datetime.now()
                historial_de_estado = HistorialDeEstado(fecha = fecha,
                        usuario = usuario.id,
                        estado = nuevo_estado_ticket.id,
                        ticket = intervencion.ticket.id)
                intervencion.ticket.set(estado_actual=nuevo_estado_ticket.id)
                # Derivamos a mesa de ayuda nuevamente
                if nombre in ('En espera por grupo', 'Resuelta', 'Finalizada'):
                    grupo = GrupoDeResolucion.selectBy(nombre="MesaDeAyuda")[0]
                    intervencion.ticket.set(grupo_de_resolucion=grupo)
    
    def intervenciones_pendientes(self, intervencion):
        bandera = False
        intervenciones = intervencion.ticket.intervenciones
        for intervencion in intervenciones:
            if intervencion.estado == 'En espera por grupo':
                bandera = True
                break
        return bandera
"""    
#########################################
#       MESA DE AYUDA
# Realiza el ABM de ticket
#########################################

class MesaDeAyuda(GrupoDeResolucion):
    def __init__(self, grupo=None):
        """Constructor por defecto.

        Keyword arguments
        grupo -- type:<class 'lib.database.GrupoDeResolucion'>
        """
        #GrupoDeResolucion.__init__(self, grupo)
        #self.grupo = grupo
        # por ahi estaria bueno levantar los ultimos 10 ticket y almacenarlos
        # acá para mostrarlo en la vista inicial
        self.tickets = {}

    def crear_ticket(self, usuario, empleado, clasificacion, descripcion,
            fecha_creacion, nro_ticket):
        """Registra en la BD y agrega a la lista el nuevo ticket.

        Crea una instancia de ticket para agregarla a la self.ticket y hace un
        set en la BD en la tabla Ticket.

        Keyword arguments:
        usuario -- usuario que registro esel ticket
        empleado -- empleado solicitante del ticket
        clasificacion -- clasificacion del problema actual
        descripcion -- descripcion del problema
        fecha_creacion -- <type 'datetime.datetime'>

        Return:
        La posicion en la cual se agrego el ticket
        """
        # Nuevo ticket: ver fecha de cierre
        nuevo_ticket = Ticket(fecha_cierre = None,
                numero_ticket = nro_ticket,
                fecha_creacion = fecha_creacion,
                descripcion = descripcion,
                grupo_de_resolucion = usuario.grupo_de_resolucion.id,
                empleado = empleado.id,
                usuario_creacion = usuario.id,
                usuario_cierre = None,
                clasificacion_actual = clasificacion.id,
                estado_actual = None)
        # Primera intervencion: sin observaciones por el momento
        intervencion = Intervencion(fecha = fecha_creacion,
                clasificacion = clasificacion.id,
                grupo_de_resolucion = usuario.grupo_de_resolucion.id,
                ticket = nuevo_ticket.id)
        intervencion.set(estado='Trabajando')
        # Historial de clasificacion
        historial_de_clasificacion = HistorialDeClasificacion(
                fecha = fecha_creacion,
                clasificacion = clasificacion.id,
                ticket = nuevo_ticket.id)
        # Estado: consulto la BD y asigno al estado este historial
        estado = Estado.selectBy(nombre='Abierto en Mesa de Ayuda')[0]

        # Historial de estado
        historial_de_estado = HistorialDeEstado(fecha = fecha_creacion,
                usuario = usuario.id,
                estado = estado.id,
                ticket = nuevo_ticket.id)
        nuevo_ticket.set(estado_actual = estado.id)
        self.tickets[nuevo_ticket.numero_ticket] = nuevo_ticket
       # print self.tickets
        return nuevo_ticket

    def cerrar_ticket(self, usuario_logueado, observacion, fecha_cierre, ticket):
        """Realiza el cierre del ticket de la posicion 'pos'.

        Keyword arguments:
        usuario_logueado -- usuario que realiza el cierre
        observacion -- observacion de la intervencion
        fecha_cierre -- <type 'datetime.datetime'>

        """
        estado = Estado.selectBy(nombre='Cerrado')[0]
        historial_de_estado=HistorialDeEstado(fecha=fecha_cierre,
                usuario=usuario_logueado.id,
                estado=estado.id,
                ticket=self.tickets[ticket.numero_ticket].id)
        self.tickets[ticket.numero_ticket].set(cerrado=True,
                fecha_cierre=fecha_cierre)
        self.tickets[ticket.numero_ticket].set(estado_actual = estado.id)
        if ticket.intervenciones[0].estado != 'Resuelta':
            self.tickets[ticket.numero_ticket].intervenciones[0].set(estado='Resuelta')
        self.tickets[ticket.numero_ticket].intervenciones[-1].agregar_observaciones(
                observacion,
                usuario_logueado,
                fecha_cierre,
                self.tickets[ticket.numero_ticket].grupo_de_resolucion)
        """
        obs = Observacion(descripcion=observacion,
                grupo_de_resolucion=self.tickets[ticket.numero_ticket].grupo_de_resolucion.id,
                intervencion=self.tickets[ticket.numero_ticket].intervenciones[-1].id,
                usuario=usuario_logueado.id,
                fecha=fecha_cierre)
        """
        del self.tickets[ticket.numero_ticket]

    def derivar_ticket(self, grupo, fecha_derivacion, obs, usuario, ticket,
            clasificacion = None):
        """Realiza la derivacion del ticket.

        Keyword arguments:
        """
        if clasificacion:
            #Llamada desde buscar, quiere decir que se re-clasifico
            historial_de_clasificacion = HistorialDeClasificacion(
                    fecha = fecha_derivacion,
                    clasificacion = clasificacion.id,
                    ticket = self.tickets[ticket.numero_ticket].id)
        estado = Estado.selectBy(nombre='Derivado en espera')[0]
        self.tickets[ticket.numero_ticket].set(grupo_de_resolucion = grupo.id)
        # Actualizamos la BD
        historial_de_estado = HistorialDeEstado(fecha = fecha_derivacion,
                usuario = usuario.id,
                estado = estado.id,
                ticket = self.tickets[ticket.numero_ticket].id)
        #Agregamos una obs a la intervencion
        self.tickets[ticket.numero_ticket].intervenciones[-1].agregar_observaciones(
                observacion,
                usuario_logueado,
                fecha_cierre,
                self.tickets[ticket.numero_ticket].grupo_de_resolucion)
        """
        observacion = Observacion(descripcion = obs,
                grupo_de_resolucion = grupo.id,
                intervencion = self.tickets[ticket.numero_ticket].intervenciones[-1].id,
                usuario = usuario.id,
                fecha = fecha_derivacion)
        """
        # Por defecto la nueva intervencion tiene el estado en espera por
        # trabajar.
        # Si el grupo al cual derivamos no tiene una intervencion pendiente,
        # creamos una nueva intervencion para el grupo.
        bandera = False
        for intervencion in ticket.intervenciones:
            if (intervencion.estado == 'En espera por grupo' and
                    intervencion.grupo_de_resolucion == grupo):
                bandera = True
                break
        if bandera:
            intervencion.set(estado = 'En espera por trabajar')
        else:
            intervencion = Intervencion(fecha = fecha_derivacion,
                    clasificacion = self.tickets[ticket.numero_ticket].clasificacion_actual.id,
                    grupo_de_resolucion = grupo.id,
                    ticket = self.tickets[ticket.numero_ticket].id)
        # Si mesa de ayuda deriva ponemos la intervencion [0] en estado
        # 'Finalizada'. Quiere decir que mesa de ayuda termino su trabajo
        intervencion_mesa_ayuda = self.tickets[ticket.numero_ticket].intervenciones[0]
        if intervencion_mesa_ayuda.estado != 'Finalizada':
            intervencion_mesa_ayuda.set(estado='Finalizada')
        # Establecemos el estado actual
        self.tickets[ticket.numero_ticket].set(estado_actual = estado.id)
        del self.tickets[ticket.numero_ticket]
        
    def buscar_ticket(self,
            empleado,
            ultimo_grupo,
            clasificacion,
            estado,
            nro_ticket,
            fecha_apertura_desde,
            fecha_apertura_hasta,
            fecha_ultimo_cambio_desde,
            fecha_ultimo_cambio_hasta):
        """Busca los tickets que cumplen con lo criterios de busqueda.

        Recorrera la lista de tiket que tenemos en memoria y irá creando la
        'lista_ticket', luego consultará la BD para obtener mas ticket,
        creando con ellos nuevos ticket para ya tenerlos en la memoria.

        Return:
        lista_ticket -- [<class 'lib.ticket'>]
        """
        # Algunos casos
        lista_ticket = []
        if empleado:
            lista_ticket = self.buscar_ticket_empleado(empleado,
                    clasificacion, ultimo_grupo, estado, nro_ticket)
            if lista_ticket:
                lista = self.depurar_con_fechas(lista_ticket,fecha_apertura_desde,
                        fecha_apertura_hasta,
                        fecha_ultimo_cambio_desde,
                        fecha_ultimo_cambio_hasta)
                return lista
            else:
                return None
        elif nro_ticket:
            lista_ticket = self.buscar_nro_ticket(clasificacion, ultimo_grupo,
                    estado, nro_ticket)
            if lista_ticket:
                lista = self.depurar_con_fechas(lista_ticket,fecha_apertura_desde,
                        fecha_apertura_hasta,
                        fecha_ultimo_cambio_desde,
                        fecha_ultimo_cambio_hasta)
                return lista
            else:
                return None
        else:
            # No me puso empleado, entonces tenemos que buscar por lo otro.
            # Chanchada de codigo
            print clasificacion
            print estado
            print ultimo_grupo
            if clasificacion == 'Todas':
                clasificacion = ''
            else:
                clasificacion = clasificacion.id
            if estado == None:
                estado = ''
            else:
                estado = estado.id
            if ultimo_grupo == "Todos":
                ultimo_grupo = ''
            else:
                ultimo_grupo = ultimo_grupo.id
            # Me cagaron con fecha de ultimo cambio
            tupla_valores = (clasificacion,
                    estado,
                    ultimo_grupo)
            consulta_valores = (
                    '(ticket.clasificacion_actual_id = %d)',
                    '(ticket.estado_actual_id = %d)',
                    '(ticket.grupo_de_resolucion_id = %d)')
            consulta_sql = ''
            for pos, dato in enumerate(tupla_valores):
                if dato:
                    print dato
                    cadena = consulta_valores[pos] % dato
                    if consulta_sql:
                        cadena = consulta_valores[pos] % dato
                        consulta_sql+=' AND ' + cadena
                    else:
                        consulta_sql+=cadena
            print consulta_sql
            if consulta_sql:
                resultado = Ticket.select(consulta_sql,
                    clauseTables=['ticket'])
                lista_ticket = self.depurar_con_fechas(list(resultado),
                        fecha_apertura_desde,
                        fecha_apertura_hasta,
                        fecha_ultimo_cambio_desde,
                        fecha_ultimo_cambio_hasta)
                        
            else:
                resultado =  Ticket.select()
                lista_ticket = self.depurar_con_fechas(list(resultado),
                        fecha_apertura_desde,
                        fecha_apertura_hasta,
                        fecha_ultimo_cambio_desde,
                        fecha_ultimo_cambio_hasta)
            # Retornamos los ticket
            return lista_ticket
    
    def depurar_con_fechas(self, lista_ticket,
            fecha_apertura_desde, fecha_apertura_hasta,
            fecha_ultimo_cambio_desde, fecha_ultimo_cambio_hasta):
        """Filtrara con las fechas validas"""
        lista_fecha_apertura = []
        lista_resultado = []
        # Fecha de Apertura iguales, buscamos por ese dia
        if fecha_apertura_desde.date() == fecha_apertura_hasta.date():
            for ticket in lista_ticket:
                if (ticket.fecha_creacion.date() ==
                        fecha_apertura_desde.date()):
                    lista_fecha_apertura.append(ticket)
        else:
            for ticket in lista_ticket:
                if ((ticket.fecha_creacion.date() >=
                    fecha_apertura_desde.date()) and (
                        ticket.fecha_creacion.date() <=
                        fecha_apertura_hasta.date())):
                            lista_fecha_apertura.append(ticket)
        # Fechas de último cambio
        if fecha_ultimo_cambio_desde == fecha_ultimo_cambio_hasta:
            for ticket in lista_fecha_apertura:
                pdb.set_trace()
                fecha = ticket.historial_de_estado[-1].fecha
                if (fecha.date() == fecha_ultimo_cambio_desde.date()):
                    if ticket not in lista_resultado:
                        lista_resultado.append(ticket)
        else:
            for ticket in lista_fecha_apertura:
                fecha = ticket.historial_de_estado[-1].fecha
                if (fecha.date() >= fecha_ultimo_cambio_desde.date()
                        and fecha.date() <=
                        fecha_ultimo_cambio_hasta.date()):
                    if ticket not in lista_resultado:
                        lista_resultado.append(ticket)
        return lista_resultado

    def buscar_ticket_BD(self, nro_ticket, empleado):
        """Busca en la BD el ticket con el numero 'nro_ticket'.

        Si el empleado es igual a 'empleado' devuelve el ticket. Sino devuelve
        una lista vacia.
        """
        consulta = Ticket.selectBy(numero_ticket = nro_ticket,
                empleado = empleado.id)
        # Tenemos el ticket y es del empleado. Creamos el ticket y
        # devolvemos True
        ticket = list(consulta)
        if ticket:
            return ticket[0], True
        else:
            return '', False

    def buscar_ticket_empleado(self, empleado, clasificacion, ultimo_grupo,
            estado, nro_ticket):
        """Buscar ticket si tenemos el empleado en el formulario"""
        lista_ticket = []
        if (clasificacion == "Todas" and
                ultimo_grupo == "Todos" and
                estado == None):
            if nro_ticket:
                # Busco el ticket con ese numero y que sea del empleado
                if self.tickets.get(nro_ticket):
                    lista_ticket.append(self.tickets.get(nro_ticket))
                    return lista_ticket
                else:
                    ticket, flag = self.buscar_ticket_BD(nro_ticket, empleado)
                    if flag:
                        lista_ticket.append(ticket)
                        return lista_ticket
                    else:
                        return None
            else:
                # Busco todos los ticket que tenga el empleado
                return empleado.tickets_reclamados
        elif estado:
            if nro_ticket:
                if self.tickets.get(nro_ticket):
                    ticket = self.tickets.get(nro_ticket)
                    if ticket.estado_actual == estado:
                        lista_ticket.append(ticket)
                        return lista_ticket
                    else:
                        return None
                else:
                    consulta = list(Ticket.selectBy(numero_ticket=nro_ticket,
                            estado_actual=estado))
                    if consulta:
                        lista_ticket.append(consulta[0])
                        return lista_ticket
                    else:
                        return None
            else:
                # Solo puso el empleado y tenemos que retornar los tickets con
                # ese estado
                lista = empleado.tickets_reclamados
                for ticket in lista:
                    if ticket.estado_actual == estado:
                        lista_ticket.append(ticket)
                print "Empleado + estado"
                return lista_ticket
        elif clasificacion!='Todas':
            if nro_ticket:
                if self.tickets.get(nro_ticket):
                    ticket = self.tickets.get(nro_ticket)
                    if ticket.clasificacion_actual == clasificacion:
                        lista_ticket.append(ticket)
                        return lista_ticket
                    else:
                        return None
                else:
                    consulta = list(Ticket.selectBy(numero_ticket=nro_ticket,
                            clasificacion_actual=clasificacion))
                    if consulta:
                        lista_ticket.append(consulta[0])
                        return lista_ticket
                    else:
                        return None
            else:
                # No puso el número del ticket. Devolvemos todos los tickets
                # que tengan esa clasificacion
                lista = empleado.tickets_reclamados
                for ticket in lista:
                    if ticket.clasificacion_actual == clasificacion:
                        lista_ticket.append(ticket)
                print "Empleado + clasificacion"
                return lista_ticket
        elif ultimo_grupo!='Todos':
            if nro_ticket:
                if self.tickets.get(nro_ticket):
                    ticket = self.tickets.get(nro_ticket)
                    if ticket.grupo_de_resolucion == ultimo_grupo:
                        lista_ticket.append(ticket)
                        return lista_ticket
                    else:
                        return None
                else:
                    consulta = list(Ticket.selectBy(numero_ticket=nro_ticket,
                            grupo_de_resolucion=utimo_grupo))
                    if consulta:
                        lista_ticket.append(consulta[0])
                        return lista_ticket
                    else:
                        return None
            else:
                # No puso el número del ticket. Devolvemos todos los tickets
                # que tengan esa clasificacion
                lista = empleado.tickets_reclamados
                for ticket in lista:
                    if ticket.grupo_de_resolucion == ultimo_grupo:
                        lista_ticket.append(ticket)
                print "Empleado + grupo de resolucion"
                return lista_ticket

    def buscar_nro_ticket(self, clasificacion, ultimo_grupo,
            estado, nro_ticket):
        """lo"""

        lista_ticket = []
        if(nro_ticket and
                clasificacion == "Todas" and
                ultimo_grupo == "Todos" and
                estado == None):
            if self.tickets.get(nro_ticket):
                lista_ticket.append(self.tickets.get(nro_ticket))
                if lista_ticket:
                    print "Lo tengo en memoria"
                    return lista_ticket
            else:
                consulta = list(Ticket.selectBy(numero_ticket=nro_ticket))
                if consulta:
                    lista_ticket.append(consulta[0])
                    return lista_ticket
                else:
                    return None
        elif estado:
            # El usuario selecciono numero ticket y estado 
            if self.tickets.get(nro_ticket):
                ticket = self.tickets.get(nro_ticket)
                if ticket.estado_actual == estado:
                    lista_ticket.append(ticket)
                    return lista_ticket
                else:
                    return None
            else:
                consulta = list(Ticket.selectBy(numero_ticket=nro_ticket,
                            estado_actual=estado))
                if consulta:
                    lista_ticket.append(consulta[0])
                    return lista_ticket
                else:
                    return None
        elif clasificacion!='Todas':
            # El usuario selecciono numero ticket y clasificacion
            if self.tickets.get(nro_ticket):
                ticket = self.tickets.get(nro_ticket)
                if ticket.clasificacion_actual == clasificacion:
                    lista_ticket.append(ticket)
                    return lista_ticket
                else:
                    return None
            else:
                consulta = list(Ticket.selectBy(numero_ticket=nro_ticket,
                            clasificacion_actual=clasificacion))
                if consulta:
                    lista_ticket.append(consulta[0])
                    return lista_ticket
                else:
                    return None
        elif ultimo_grupo!='Todos':
            # El usuario selecciono numero ticket y clasificacion
            if self.tickets.get(nro_ticket):
                ticket = self.tickets.get(nro_ticket)
                if ticket.grupo_de_resolucion == ultimo_grupo:
                    lista_ticket.append(ticket)
                    return lista_ticket
                else:
                    return None
            else:
                consulta = list(Ticket.selectBy(numero_ticket=nro_ticket,
                            grupo_de_resolucion=ultimo_grupo))
                if consulta:
                    lista_ticket.append(consulta[0])
                    print lista_ticket
                    return lista_ticket
                else:
                    return None
    
    def configurar_reporte(self):
        pass

    def visualizar_informacion_por_ticket(self):
        pass

    def visualizar_informacion_por_legajo(self):
        pass

    def visualizar_informacion_por_estado_actual(self):
        pass

    def visualizar_informacion_por_ultimo_grupo(self):
        pass

    def visualizar_informacion_por_clasificacion_actual(self):
        pass
